﻿using GrapeCity.Forguncy.CellTypes;
using GrapeCity.Forguncy.Commands;
using GrapeCity.Forguncy.Plugin;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Vant.Properties;

namespace Vant.CellTypes
{
    public class CascaderDesigner : InputCellTypeBaseDesigner<Cascader>
    {
        public override void InitDefaultPropertyValues(IBuilderContext context)
        {
            base.InitDefaultPropertyValues(context);
            var list = JsonConvert.DeserializeObject<List<TreeNode>>(Properties.Resources.DefaultTreeSource);
            this.CellType.options = list.OfType<ITreeNode>().ToList();
            this.CellType.CascaderConfig.title = Resources.Cascader_CascaderConfig_Title_DefaultValue;
        }
    }

    [Designer("Vant.CellTypes.CascaderDesigner, Vant")]
    [Icon("pack://application:,,,/Vant;component/Resources/Images/Calendar.png")]
    [OrderWeight((int)Utils.OrderWeight.Cascader)]
    public class Cascader : InputCellTypeBase 
    {
        public override List<Command> CommandList { get => base.CommandList; set => base.CommandList = value; }
        public override DataValidationLink DataValidationLink { get => base.DataValidationLink; set => base.DataValidationLink = value; }
        public override List<UIPermission> UIPermissions { get => base.UIPermissions; set => base.UIPermissions = value; }
        public override object DefaultValue { get => base.DefaultValue; set => base.DefaultValue = value; }

        [SRDisplayName(nameof(Resources.UseBinding))]
        [BoolProperty]
        [MergableProperty(false)]
        public bool useBinding { get; set; } = false;

        [SRTreeProperty(IndentLevel = 1, NodeType = typeof(TreeNode), DefaultNodeName = nameof(Resources.Cascader_Options_DefaultNodeName))]
        [SRDisplayName(nameof(Resources.Options))]
        public List<ITreeNode> options { get; set; } = new List<ITreeNode>();

        [SRDisplayName(nameof(Resources.BindingOptions))]
        [SRBindingDataSourceProperty(Columns = nameof(Resources.Cascader_BindingOptions_Columns), IndentLevel = 1,
            IsIdPidStructure = true, TreeIdColumnName = "value", TreePidColumnName = "parentValue")]
        public object bindingOptions { get; set; }

        public override string placeholder { get => base.placeholder; set => base.placeholder = value; }
        public override ImageValue leftIcon { get => base.leftIcon; set => base.leftIcon = value; }
        public override ImageValue rightIcon { get => base.rightIcon; set => base.rightIcon = value; }
        public override bool border { get => base.border; set => base.border = value; }
        public override bool clearable { get => base.clearable; set => base.clearable = value; }
        public override bool ReadOnly { get => base.ReadOnly; set => base.ReadOnly = value; }
        public override bool IsDisabled { get => base.IsDisabled; set => base.IsDisabled = value; }

        [ObjectProperty(ObjType = typeof(CascaderConfig))]
        [SRDisplayName(nameof(Resources.PopupSettings))]
        public CascaderConfig CascaderConfig { get; set; } = new CascaderConfig();

        public override bool GetDesignerPropertyVisible(string propertyName)
        {
            if (propertyName == nameof(options))
            {
                return !useBinding;
            }
            if (propertyName == nameof(bindingOptions))
            {
                return useBinding;
            }
            return base.GetDesignerPropertyVisible(propertyName);
        }

        [SRDisplayName(nameof(Resources.Cascader_ShowPopup))]
        [RunTimeMethod]
        public void ShowPopup()
        {
        }


        [RunTimeMethod]
        [SRDisplayName(nameof(Resources.SetDataSourceByObjTree))]
        [SRDescription(nameof(Resources.Cascader_SetDataSourceByObjTree_Description))]
        public void SetDataSourceByObjTree(
                [SRItemDisplayName(nameof(Resources.DataSource))]
                [Required]
                string dataSource,

                [SRItemDisplayName(nameof(Resources.ValueProperty))]
                [SRDescription(nameof(Resources.Cascader_SetDataSourceByObjTree_ValueProperty_Description))]
                [Required]
                string valueProperty = "value",

                [SRItemDisplayName(nameof(Resources.LabelProperty))]
                [SRDescription(nameof(Resources.Cascader_SetDataSourceByObjTree_LabelProperty_Description))]
                string labelProperty = "label",

                [SRItemDisplayName(nameof(Resources.Cascader_SetDataSourceByObjTree_ChildrenProperty))]
                [SRDescription(nameof(Resources.Cascader_SetDataSourceByObjTree_ChildrenProperty_Description))]
                [Required]
                string childrenProperty = "children")
        {

        }

        [RunTimeMethod]
        [SRDisplayName(nameof(Resources.SetDataSourceByIdPidTable))]
        [SRDescription(nameof(Resources.Cascader_SetDataSourceByIdPidTable_Description))]
        public void SetDataSourceByIdPidTable(
                [SRItemDisplayName(nameof(Resources.DataSource))]
                [Required]
                string dataSource,

                [SRItemDisplayName(nameof(Resources.ValueProperty))]
                [Required]
                string valueProperty = "value",

                [SRItemDisplayName(nameof(Resources.LabelProperty))]
                [SRDescription(nameof(Resources.SetDataSourceByIdPidTable_labelProperty_Description))]
                string labelProperty = "label",

                [SRItemDisplayName(nameof(Resources.ParentValue))]

                [Required]
                string parentValue = "parentValue")
        {

        }

        public override string ToString()
        {
            return Properties.Resources.Cascader;
        }
        public override SupportFeatures SupportFeatures => base.SupportFeatures | SupportFeatures.AllowSetFormat;

    }

    public class CascaderConfig : ObjectPropertyBase
    {
        [SRDisplayName(nameof(Properties.Resources.Vant_ShowToolbar))]
        [DefaultValue(true)]
        public bool showToolbar { get; set; } = true;

        [SRDisplayName(nameof(Resources.Cascader_CascaderConfig_Title))]
        public string title { get; set; }

        [SRDisplayName(nameof(Resources.Cascader_CascaderConfig_Closeable))]
        [DefaultValue(true)]
        public bool closeable { get; set; } = true;

        [ColorProperty]
        [SRDisplayName(nameof(Resources.Cascader_CascaderConfig_ActiveColor))]
        public string activeColor { get; set; } = "Accent 1";

        [SRDisplayName(nameof(Resources.Cascader_CascaderConfig_Swipeable))]
        public bool swipeable{ get; set; }

        public override bool GetDesignerPropertyVisible(string propertyName)
        {
            if (propertyName == nameof(title) ||
                propertyName == nameof(closeable))
            {
                return showToolbar;
            }
            return base.GetDesignerPropertyVisible(propertyName);
        }
    }

    public class TreeNode : TreeNodeBase<TreeNode>
    {

    }

    public class TreeNodeBase<T> : ITreeNode, ICloneable where T : ITreeNode
    {
        [SRDisplayName(nameof(Resources.Value))]
        [Required]
        public string value { get; set; }

        [SRDisplayName(nameof(Resources.Label))]
        [Required]
        public string text { get; set; }

        public List<T> children { get; set; } = new List<T>();

        public bool ShouldSerializechildren()
        {
            return children.Count != 0;
        }

        string ITreeNode.Text
        {
            get
            {
                return text;
            }
            set
            {
                if (text == this.value)
                {
                    this.value = value;
                }
                text = value;
            }
        }

        IEnumerable<ITreeNode> ITreeNode.Children
        {
            get
            {
                return children as IEnumerable<ITreeNode>;
            }
            set
            {
                children = value.OfType<T>().ToList();
            }
        }

        public object Clone()
        {
            return PluginUtilities.CommonClone(this);
        }
    }
}
